package com.springvision.core.tcpserver;

import java.nio.charset.Charset;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public abstract class TCPServer {

	@Autowired
	@Qualifier("serverChannelHandler")
	protected ChannelHandler channelHandler;

	/** 用于分配处理业务线程的线程组个数 */
	private static final int BIZGROUPSIZE = Runtime.getRuntime().availableProcessors() * 2; // 默认

	/** 业务出现线程大小 */
	private static final int BIZTHREADSIZE = 4;

	protected String ip = "0.0.0.0";

	/** 绑定端口号 */
	protected int port = 10081;

	protected abstract void start() throws InterruptedException;

	public void run() throws InterruptedException {
		new Thread(new Runnable() {

			@Override
			public void run() {
				EventLoopGroup bossGroup = new NioEventLoopGroup(BIZGROUPSIZE);
				EventLoopGroup workerGroup = new NioEventLoopGroup(BIZTHREADSIZE);
				try {
					ServerBootstrap b = new ServerBootstrap();
					b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
							.childHandler(new ChannelInitializer<SocketChannel>() {

								@Override
								public void initChannel(SocketChannel ch) throws Exception {
									ChannelPipeline pipeline = ch.pipeline();
									ByteBuf delimiter = Unpooled.copiedBuffer("|".getBytes());
									
									
									// 以("\n")为结尾分割的 解码器 Delimiters  |
									pipeline.addLast("framer",new DelimiterBasedFrameDecoder(8192, delimiter));
									// 字符串解码 和 编码
									
//									pipeline.addLast("decoder", new StringDecoder(Charset.forName("GB2312")));
									pipeline.addLast("decoder", new StringDecoder());
									pipeline.addLast("encoder", new StringEncoder());
									// 自己的逻辑Handler
									pipeline.addLast(channelHandler);
								}
							}).option(ChannelOption.SO_BACKLOG, 1024); // 客户端请求队列大小
					// .childOption(ChannelOption.SO_KEEPALIVE, true); // 长连接
					ChannelFuture f;
					try {
						f = b.bind(ip, port).sync();
						f.channel().closeFuture().sync();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

				} finally {
					workerGroup.shutdownGracefully();
					bossGroup.shutdownGracefully();
				}
			}

		}).start();

	}

}
